package com.fangs.kotlin_banner.banner

import android.content.Context
import android.os.Handler
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.view.ViewCompat
import androidx.viewpager.widget.ViewPager
import com.fangs.kotlin_banner.adapter.BannerViewAdapter
import com.fangs.kotlin_banner.utils.ImageLoaderUtils
import java.util.ArrayList

class Banner : LinearLayout {
    private var viewPager: ViewPagerBanner? = null

    //默认视频时间（考虑视频初加载无法获得时长）
    private val vidoDelyed = 5000

    //图片默认时间
    private var delyedTime = 2000

    //默认显示位置
    private var autoCurrIndex = 0
    private var views: MutableList<View>? = null
    private var mAdapter: BannerViewAdapter? = null
    private var pageChangeListener: OnPageChangeListener? = null
    private var itemClickListener: OnItemClickListener? = null
    private var listBanner: MutableList<BannerPage>? = null
    private var onPause = false
    private var videoTimeRunnable: VideoTimeRunnable? = null

    /**
     * 发消息，进行循环
     */
    private var runnable: Runnable? = Runnable {
        smoothed = false
        viewPager?.setCurrentItem(autoCurrIndex + 1, autoCurrIndex != 0)
        if (!smoothed) {
            mHandler!!.postDelayed({
                viewPager?.setCurrentItem(
                    autoCurrIndex + 1,
                    true
                )
            }, 2000)
        }
    }
    private var smoothed = false //笨办法 处理上层页面通过侧滑退出后 banner.onResume执行却仍 轮播中止问题

    //接受消息实现轮播
    private var mHandler: Handler? = Handler()
    private var mDownX = 0
    private var mDownY = 0
    private var horizontal = false

    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init()
    }

    private fun init() {
        videoTimeRunnable = VideoTimeRunnable()
        val vp_param = LayoutParams(
            LayoutParams.MATCH_PARENT,
            LayoutParams.MATCH_PARENT
        )
        viewPager = ViewPagerBanner(context)
        viewPager!!.setLayoutParams(vp_param)
        //增加翻页视差效果
        viewPager!!.setPageTransformer(
            true,
            ViewPager.PageTransformer { page: View, position: Float ->
                val width = page.width
                if (position < -1) {
                    page.scrollX = (width * 0.8 * -1).toInt()
                } else if (position <= 1) {
                    page.scrollX = (width * 0.8 * position).toInt()
                } else {
                    page.scrollX = (width * 0.8).toInt()
                }
            },
            ViewCompat.LAYER_TYPE_NONE
        )
        this.addView(viewPager)
    }

    /**
     * 设置ViewPager是否可以滑动，默认false不可滑动
     *
     * @param isSlide boolean;//
     */
    fun setSlide(isSlide: Boolean) {
        viewPager?.setSlide(isSlide)
    }

    fun setPageChangeListener(pageChangeListener: OnPageChangeListener?) {
        this.pageChangeListener = pageChangeListener
    }

    fun setItemClickListener(itemClickListener: OnItemClickListener?) {
        this.itemClickListener = itemClickListener
    }

    /**
     * 设置滚动广告，图片，视频
     */
    fun setBanner() {
        mAdapter = BannerViewAdapter(views)
        mAdapter!!.setOnClicked(object: BannerViewAdapter.OnClicked{
            override fun onItemClicked(positions: Int) {
                itemClickListener?.onItemClick(positions)
            }
        })
        viewPager?.setAdapter(mAdapter)
        viewPager?.setCurrentItem(autoCurrIndex, false) //跳转到指定页面
        viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
            }

            override fun onPageSelected(position: Int) {
                //当前位置
                autoCurrIndex = position
                if (pageChangeListener != null) {
                    // 此处 针对Banner中setDataList循环数组将首尾各加一条数据情况 将角标做对应处理
                    val p =
                        if (position == 0) views!!.size - 3 else if (position == views!!.size - 1) 0 else position - 1
                    pageChangeListener!!.onPageSelected(p)
                }
            }

            override fun onPageScrollStateChanged(state: Int) {
                smoothed = true
                //ViewPager跳转
                var pageIndex = autoCurrIndex
                if (autoCurrIndex == 0) {
                    pageIndex = views!!.size - 2
                } else if (autoCurrIndex == views!!.size - 1) {
                    pageIndex = 1
                }
                if (views!!.size == 1) { //此处考虑到 只有一项时触摸滑动也会触发当前方法 故做出判断避免角标越界
                    pageIndex = 0
                }
                if (pageIndex != autoCurrIndex) {
                    //无滑动动画，直接跳转
                    viewPager!!.setCurrentItem(pageIndex, false)
                }
                if (state == 0) {
                    setAutoPlay(pageIndex)
                }
            }
        })
    }

    //开启自动循环
    fun setAutoPlay(curPos: Int) {
        val view1 = views!![curPos]
        if (view1 is MyVideoLayout) {
            val videoLayout: MyVideoLayout = view1 as MyVideoLayout
            if (videoLayout.videoView!!.isPlaying()) {
                delyedTime =
                    videoLayout.videoView!!.getDuration() - videoLayout.videoView!!.getCurrentPosition()
            } else {
                videoLayout.videoView!!.seekTo(0)
                videoLayout.videoView!!.start()
                delyedTime = videoLayout.videoView!!.getDuration() //单位毫秒（ms）
                videoTimeRunnable!!.getDelyedTime(videoLayout, runnable)
            }
        } else {
            delyedTime = listBanner!![curPos].imgDelyed
        }
        //移除自动计时
        mHandler!!.removeCallbacksAndMessages(null)
        if (views!!.size > 1) {
            if (delyedTime < 0) { //此处默认是只有视频情况下才会拿不到时间
                mHandler!!.postDelayed(videoTimeRunnable!!, vidoDelyed.toLong())
            } else {
                mHandler!!.postDelayed(runnable!!, delyedTime.toLong())
            }
        }
    }

    /**
     * 设置数据
     *
     * @param dataList,//轮播数组
     * @param index,//插播地址，   -1时采用默认
     */
    private fun setDataList(dataList: List<BannerPage>?, index: Int) {
        var dataList: List<BannerPage>? = dataList
        listBanner = ArrayList<BannerPage>()
        if (index != -1) {
            autoCurrIndex = index
        }
        if (dataList == null) {
            dataList = ArrayList<BannerPage>()
        }
        //用于显示的数组
        if (views == null) {
            views = ArrayList()
        } else {
            views!!.clear()
        }

        //数据大于一条，才可以循环
        if (dataList!!.size > 1) {
            if (autoCurrIndex < 0 || autoCurrIndex > dataList.size - 1) {
                autoCurrIndex = 1
            } else {
                autoCurrIndex++
            }
            //循环数组，将首尾各加一条数据
            for (i in 0 until dataList.size + 2) {
                var bannerPage: BannerPage
                bannerPage = if (i == 0) {
                    dataList[dataList.size - 1]
                } else if (i == dataList.size + 1) {
                    dataList[0]
                } else {
                    dataList[i - 1]
                }
                listBanner!!.add(bannerPage)
                if (bannerPage.isVideo) {
                    val videoLayout = MyVideoLayout(context, false)
                    videoLayout.videoView!!.setUrl(bannerPage.url)
                    ImageLoaderUtils.display(context, videoLayout.imageView, bannerPage.thum)
                    views!!.add(videoLayout)
                } else {
                    val imageView = ImageView(context)
                    imageView.scaleType = ImageView.ScaleType.CENTER_CROP
                    ImageLoaderUtils.display(context, imageView, bannerPage.url)
                    views!!.add(imageView)
                }
            }
        } else if (dataList.size == 1) {
            autoCurrIndex = 0
            val bannerPage: BannerPage = dataList[0]
            listBanner!!.add(bannerPage)
            if (bannerPage.isVideo) {
                val videoLayout = MyVideoLayout(context, true)
                videoLayout.videoView!!.setUrl(bannerPage.url)
                ImageLoaderUtils.display(context, videoLayout.imageView, bannerPage.thum)
                views!!.add(videoLayout)
            } else {
                val imageView = ImageView(context)
                imageView.scaleType = ImageView.ScaleType.CENTER_CROP
                ImageLoaderUtils.display(context, imageView, bannerPage.url)
                views!!.add(imageView)
            }
        } else {
            autoCurrIndex = 0
            listBanner!!.add(BannerPage("", 0))
            views!!.add(LinearLayout(context))
        }
    }

    /**
     * 设置数据并播放
     *
     * @param dataList,//轮播数组
     */
    fun setDataPlay(dataList: List<BannerPage>?) {
        setDataPlay(dataList, -1)
    }

    /**
     * 设置数据并播放
     *
     * @param dataList,//轮播数组
     * @param index,//插播地址，   -1时采用默认
     */
    fun setDataPlay(dataList: List<BannerPage>?, index: Int) {
        setDataList(dataList, index)
        setBanner()
        setAutoPlay(autoCurrIndex)
    }

    fun onResume() {
        if (onPause && views != null && views!!.size > 1) {
            delyedTime = if (listBanner!![autoCurrIndex].isVideo) {
                (views!![autoCurrIndex] as MyVideoLayout).videoLimitTime
            } else {
                listBanner!![autoCurrIndex].imgDelyed
            }
            mHandler!!.removeCallbacksAndMessages(null)
            mHandler!!.postDelayed(runnable!!, delyedTime.toLong())
        }
        onPause = false
    }

    fun onPause() {
        mHandler!!.removeCallbacksAndMessages(null)
        if (views != null && views!!.size > 1) {
            if (autoCurrIndex == views!!.size - 2) { //此处作用是配合 smoothed 字段的目的使用 都是东拼西凑的笨办法 因为并没有真正找到侧滑退出操作会中止首页轮播的原因
                autoCurrIndex = 0
            }
        }
        onPause = true
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                mDownX = ev.x.toInt()
                mDownY = ev.y.toInt()
                horizontal = false
                mHandler!!.removeCallbacksAndMessages(null)
            }
            MotionEvent.ACTION_MOVE -> {
                val endX = ev.x.toInt()
                val endY = ev.y.toInt()
                val distanceX = Math.abs(endX - mDownX)
                val distanceY = Math.abs(endY - mDownY)
                horizontal = distanceX > 0 && distanceX > distanceY
            }
            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE -> if (views != null && views!!.size > 1) {
                delyedTime = if (listBanner!![autoCurrIndex].isVideo) {
                    val videoLayout: MyVideoLayout = views!![autoCurrIndex] as MyVideoLayout
                    videoLayout.videoView!!.getDuration() - videoLayout.videoView!!.getCurrentPosition()
                } else {
                    listBanner!![autoCurrIndex].imgDelyed
                }
                mHandler!!.removeCallbacksAndMessages(null)
                mHandler!!.postDelayed(runnable!!, delyedTime.toLong())
            }
            MotionEvent.ACTION_UP -> if (!horizontal && views != null && views!!.size > 1) { // 如果水平滑动的话 会自动触发OnPageChangeListener启动轮播 故无须执行下面的代码
                delyedTime = if (listBanner!![autoCurrIndex].isVideo) {
                    val videoLayout: MyVideoLayout = views!![autoCurrIndex] as MyVideoLayout
                    videoLayout.videoView!!.getDuration() - videoLayout.videoView!!.getCurrentPosition()
                } else {
                    listBanner!![autoCurrIndex].imgDelyed
                }
                mHandler!!.removeCallbacksAndMessages(null)
                mHandler!!.postDelayed(runnable!!, delyedTime.toLong())
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    fun destroy() {
        //说当参数为null时,删除所有回调函数和message
        // 这样做的好处是在Acticity退出的时候，可以避免内存泄露
        mHandler!!.removeCallbacksAndMessages(null)
        mHandler = null
        videoTimeRunnable = null
        runnable = null
        if (views != null) {
            views!!.clear()
            views = null
        }
        viewPager = null
        mAdapter = null
    }

    /**
     * 这个类，恩，获取视频长度，以及已经播放的时间
     */
    private inner class VideoTimeRunnable : Runnable {
        private var videoLayout: MyVideoLayout? = null
        private var runnable: Runnable? = null
        fun getDelyedTime(videoLayout: MyVideoLayout?, runnable: Runnable?) {
            this.videoLayout = videoLayout
            this.runnable = runnable
        }

        override fun run() {
            val delyedTime: Int =
                videoLayout!!.videoView!!.getDuration() - videoLayout!!.videoView!!.getCurrentPosition()
            mHandler!!.postDelayed(
                runnable!!,
                (if (delyedTime >= 0) delyedTime else vidoDelyed.toLong()) as Long
            )
        }
    }

    interface OnPageChangeListener {
        fun onPageSelected(position: Int)
    }

    interface OnItemClickListener {
        fun onItemClick(position: Int)
    }
}